/*
 * Copyright 2007. Mount Sinai Hospital, Toronto, Canada.
 * 
 * Licensed under the GNU Lesser General Public License, Version 2. You
 * can find a copy of the license at:
 * 
 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
 * 
 * IN NO EVENT SHALL MOUNT SINAI HOSPITAL BE LIABLE TO ANY PARTY FOR DIRECT, 
 * INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST 
 * PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, 
 * EVEN IF MOUNT SINAI HOSPITAL HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 
 * DAMAGE.
 * 
 * MOUNT SINAI HOSPITAL SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF 
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE AND 
 * ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS". 
 * MOUNT SINAI HOSPITAL HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, 
 * UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 
 */
package com.sinai.mshab.client.util;

import com.google.gwt.http.client.URL;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;
import com.sinai.mshab.client.ui.FormComponent;
import com.sinai.mshab.client.ui.aggregate.AggregateFormComponent;
import com.sinai.mshab.client.ui.basic.BasicFormComponent;

/**
 * The <code>Util</code> class contains miscellaneous methods that are used by
 * a number of other classes. The <code>Util</code> class allows for these
 * methods to be located in one class.
 * 
 * @author Arthur Kalmenson
 */
public class Util {

	/**
	 * Since <code>AggregateFormComponent</code> can contain
	 * <code>AggregateFormComponent</code>s and
	 * <code>BasicFormComponent</code>s, they always need to figure out what
	 * instanceof their children are before calling toPrint() on them.
	 * Therefore, this helper method allows <code>AggregateFormComponent</code>
	 * to call toPrint() on their children and not worry about what instanceof
	 * they are.
	 * 
	 * @param component
	 *            either a <code>AggregateFormComponent</code> or a
	 *            <code>BasicFormComponent</code>.
	 * @return either a {@link HorizontalPanel} or a {@link VerticalPanel} which
	 *         will contain the printable version of <code>component</code>.
	 */
	public static Widget callToPrint(FormComponent component) {

		Widget printableVersion = new Widget();

		if (component != null && component instanceof BasicFormComponent) {
			printableVersion = ((BasicFormComponent) component).toReport();
		} else if (component != null
				&& component instanceof AggregateFormComponent) {
			printableVersion = ((AggregateFormComponent) component).toReport();
		}

		return printableVersion;
	}

	/**
	 * Iterates through <code>vpanel</code> and returns a
	 * {@link VerticalPanel} containing report versions of <code>vpanel</code>'s
	 * widgets. The only non-FormComponent widgets that are included in the
	 * report are {@link Label}s.
	 * 
	 * @param vpanel
	 *            the {@link VerticalPanel} to iterate through
	 * @return report of the contents of <code>vpanel</code>
	 */
	public static VerticalPanel verticalPanelToPrint(VerticalPanel vpanel) {
		VerticalPanel printableVersion = new VerticalPanel();

		for (int i = 0; i < vpanel.getWidgetCount(); i++) {

			Widget widget = vpanel.getWidget(i);

			/*
			 * if the widget we're looking at is a BasicFormComponent or an
			 * AggregateFormComponent, we want to call their toPrint() and add
			 * it. However, if it's a regular widget, we still want to add it in
			 * order to maintain the look of the original form.
			 */
			if (widget != null && widget instanceof FormComponent) {

				// if the component is not empty, then we ask it to generate a
				// report
				FormComponent component = (FormComponent) widget;
				if (!component.isEmpty()) {
					Widget result = Util.callToPrint(component);
					if (result != null) {
						printableVersion.add(result);
					}
				}
			} else if (widget != null && widget instanceof Label) {
				Label l = (Label) widget;
				Label l_copy = new Label(l.getText());
				l_copy.setStyleName(l.getStyleName());

				printableVersion.add(l_copy);
			}
		}
		return printableVersion;
	}

	/**
	 * Returns a String appropriate for use in a POST request based on an array
	 * of {@link Entry}s. This class was created by Google and found here:
	 * http://code.google.com/webtoolkit/documentation/com.google.gwt.http.client.html
	 * 
	 * @param queryEntries
	 *            an array of {@link Entry}s that should go into the request.
	 * @return a String appropriate for use in a POST request.
	 */
	public static String buildQueryString(RequestEntry[] queryEntries) {
		StringBuffer sb = new StringBuffer();

		for (int i = 0, n = queryEntries.length; i < n; ++i) {
			RequestEntry queryEntry = queryEntries[i];

			if (i > 0) {
				sb.append("&");
			}

			// encode the characters in the name
			String encodedName = URL.encodeComponent(queryEntry.getName());
			sb.append(encodedName);

			sb.append("=");

			// encode the characters in the value
			String encodedValue = URL.encodeComponent(queryEntry.getValue());
			sb.append(encodedValue);
		}

		return sb.toString();
	}

	/**
	 * Returns only the file name if pathToFile is an absolute path, otherwise
	 * nothing is done to pathToFile. The method handles both Windows and *nix
	 * style file paths.
	 * 
	 * @param pathToFile
	 *            either the file name or the absolute path to a file.
	 * @return only the file name (without the directory/folder path before it).
	 */
	public static String parseFileName(String pathToFile) {
		String result = pathToFile;

		// if we're dealing with a Windows path.
		if (result.lastIndexOf('\\') > -1) {
			result = result.substring(result.lastIndexOf('\\') + 1);

			// if we're dealing with a *nix path.
		} else if (result.lastIndexOf('/') > -1) {
			result = result.substring(result.lastIndexOf('/') + 1);
		}

		return result;
	}

	/**
	 * Returns true if str is null or empty, and false otherwise.
	 * 
	 * @param str
	 *            the String to check.
	 * @return true if str is null or empty, and false otherwise.
	 */
	public static boolean nullEmpty(String str) {
		return (str == null || str.trim().equals(""));
	}
}
